home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / RCS / tcpOutput.c,v < prev    next >
Encoding:
Text File  |  1991-09-27  |  25.0 KB  |  969 lines

  1. head     1.8;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.8
  10. date     90.02.22.14.22.04;  author ouster;  state Exp;
  11. branches ;
  12. next     1.7;
  13.  
  14. 1.7
  15. date     89.07.23.17.35.03;  author nelson;  state Exp;
  16. branches ;
  17. next     1.6;
  18.  
  19. 1.6
  20. date     89.03.23.09.56.31;  author brent;  state Exp;
  21. branches ;
  22. next     1.5;
  23.  
  24. 1.5
  25. date     89.02.21.10.14.05;  author brent;  state Exp;
  26. branches ;
  27. next     1.4;
  28.  
  29. 1.4
  30. date     88.09.15.09.33.55;  author mendel;  state Exp;
  31. branches ;
  32. next     1.3;
  33.  
  34. 1.3
  35. date     88.08.16.11.20.22;  author mendel;  state Exp;
  36. branches ;
  37. next     1.2;
  38.  
  39. 1.2
  40. date     88.04.27.09.10.23;  author brent;  state Exp;
  41. branches ;
  42. next     1.1;
  43.  
  44. 1.1
  45. date     88.04.27.08.52.23;  author brent;  state Exp;
  46. branches ;
  47. next     ;
  48.  
  49.  
  50. desc
  51. @TCP Output routines
  52. @
  53.  
  54.  
  55. 1.8
  56. log
  57. @Added more information to debugging print-out.
  58. @
  59. text
  60. @/* 
  61.  * tcpOutput.c --
  62.  *
  63.  *    Routines to handle TCP output processing.
  64.  *
  65.  *    Based on 4.3BSD    @@(#)tcp_output.c    7.12 (Berkeley) 3/24/88
  66.  *
  67.  *    To do:
  68.  *    1) allow user-supplied TCP options to be sent with the segment.
  69.  *
  70.  *
  71.  *
  72.  * Copyright 1987 Regents of the University of California
  73.  * All rights reserved.
  74.  * Permission to use, copy, modify, and distribute this
  75.  * software and its documentation for any purpose and without
  76.  * fee is hereby granted, provided that the above copyright
  77.  * notice appear in all copies.  The University of California
  78.  * makes no representations about the suitability of this
  79.  * software for any purpose.  It is provided "as is" without
  80.  * express or implied warranty.
  81.  */
  82.  
  83. #ifndef lint
  84. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpOutput.c,v 1.7 89/07/23 17:35:03 nelson Exp $ SPRITE (Berkeley)";
  85. #endif not lint
  86.  
  87.  
  88. #include "sprite.h"
  89. #include "ipServer.h"
  90. #include "stat.h"
  91. #include "ip.h"
  92. #include "tcp.h"
  93. #include "tcpInt.h"
  94. #include "netInet.h"
  95.  
  96. /*
  97.  * Initial TCP options.
  98.  */
  99. struct {
  100.     char    kind;
  101.     char    length;
  102.     unsigned short value;
  103. } initialOptions = { 
  104.     NET_TCP_OPTION_MAX_SEG_SIZE, 
  105.     sizeof(initialOptions), 
  106.     0
  107. };
  108.  
  109. /*
  110.  * Values for the TCP header flags when in a certain state.
  111.  */
  112. static int stateToOutputFlags[] = {
  113.    NET_TCP_RST_FLAG|NET_TCP_ACK_FLAG,     /* CLOSED */
  114.    0,                     /* LISTEN */
  115.    NET_TCP_SYN_FLAG,             /* SYN_SENT */
  116.    NET_TCP_SYN_FLAG|NET_TCP_ACK_FLAG,    /* SYN_RECEIVED */
  117.    NET_TCP_ACK_FLAG,             /* ESTABLISHED */
  118.  
  119.    NET_TCP_ACK_FLAG,            /* CLOSE_WAIT */
  120.    NET_TCP_FIN_FLAG|NET_TCP_ACK_FLAG,     /* LAST_ACK */
  121.  
  122.    NET_TCP_FIN_FLAG|NET_TCP_ACK_FLAG,     /* FIN_WAIT_1 */
  123.    NET_TCP_ACK_FLAG,            /* FIN_WAIT_2 */
  124.    NET_TCP_FIN_FLAG|NET_TCP_ACK_FLAG,     /* CLOSING */
  125.    NET_TCP_ACK_FLAG,            /* TIME_WAIT */
  126. }; 
  127.  
  128. static int     timeToLive = NET_TCP_TTL;
  129. static void    CalcChecksum();
  130.  
  131.  
  132. /*
  133.  *----------------------------------------------------------------------
  134.  *
  135.  * TCPOutput --
  136.  *
  137.  *    This routine determines what data needs to be sent to the
  138.  *    remote peer.
  139.  *
  140.  * Results:
  141.  *    SUCCESS        - currently always returned.
  142.  *
  143.  * Side effects:
  144.  *    One or more packets may be sent to the network.
  145.  *
  146.  *----------------------------------------------------------------------
  147.  */
  148.  
  149. ReturnStatus
  150. TCPOutput(sockPtr, tcbPtr)
  151.     Sock_InfoPtr        sockPtr;
  152.     register TCPControlBlock    *tcbPtr;
  153. {
  154.     register int    len;
  155.     register int    window;
  156.     int            amtUnacked;
  157.     int            sendBufAmtUsed;
  158.     int            flags;
  159.     Boolean        idle;
  160.     Boolean        sendAlot;
  161.     unsigned char    *opt;
  162.     int            optlen = 0;
  163.     IPS_Packet        packet;
  164.     Address        ptr;
  165.  
  166.     /*
  167.      * Determine length of data that should be transmitted, and flags that
  168.      * will be used.  If there is some data or critical controls (SYN, RST)
  169.      * to send, then transmit; otherwise, investigate further.
  170.      *
  171.      * We're idle if all the stuff we've sent has been ACKed.
  172.      */
  173.  
  174.     idle = (tcbPtr->send.maxSent == tcbPtr->send.unAck);
  175.  
  176. again:
  177.  
  178.     sendAlot = FALSE;
  179.     amtUnacked = tcbPtr->send.next - tcbPtr->send.unAck;
  180.     window = MIN(tcbPtr->send.window, tcbPtr->send.congWindow);
  181.  
  182.     /*
  183.      * If called from the persist timeout handler with a window of 0, 
  184.      * send 1 byte.  Otherwise, if the window is small but nonzero and 
  185.      * the timer has expired, we will send what we can and go to the 
  186.      * transmit state.
  187.      */
  188.  
  189.     if (tcbPtr->force) {
  190.     if (window == 0) {
  191.         window = 1;
  192.     } else {
  193.         tcbPtr->timer[TCP_TIMER_PERSIST] = 0;
  194.         tcbPtr->rxtshift = 0;
  195.     }
  196.     }
  197.  
  198.     sendBufAmtUsed = Sock_BufSize(sockPtr, SOCK_SEND_BUF, SOCK_BUF_USED);
  199.  
  200.     len = MIN(sendBufAmtUsed, window) - amtUnacked;
  201.  
  202.     flags = stateToOutputFlags[(int)tcbPtr->state];
  203.     if (len < 0) {
  204.     /*
  205.      * If a FIN has been sent but not acked, and we haven't been
  206.      * called to retransmit, then len will be -1 so transmit if
  207.      * acking, otherwise return.  If a FIN has not been sent, the
  208.      * window shrank after we sent into it.  If the window shrank to
  209.      * 0, cancel the pending retransmit and pull send.next back to
  210.      * (closed) window.  We will enter the persist state below.  If
  211.      * the window didn't close completely, just wait for an ACK.
  212.      */
  213.  
  214.     len = 0;
  215.     if (window == 0) {
  216.         tcbPtr->timer[TCP_TIMER_REXMT] = 0;
  217.         tcbPtr->send.next = tcbPtr->send.unAck;
  218.     }
  219.     } 
  220.     if (len > tcbPtr->maxSegSize) {
  221.     len = tcbPtr->maxSegSize;
  222.     sendAlot = TRUE;
  223.     }
  224.  
  225.     /*
  226.      * If there's data to be sent, make sure the FIN flag is off.
  227.      */
  228.     if (TCP_SEQ_LT(tcbPtr->send.next+ len, tcbPtr->send.unAck+ sendBufAmtUsed)){
  229.     flags &= ~NET_TCP_FIN_FLAG;
  230.     }
  231.     window = Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_FREE); 
  232.  
  233.  
  234.     /*
  235.      * If our state indicates that FIN should be sent and we have not 
  236.      * yet done so, or we're retransmitting the FIN, then we need to send.
  237.      */
  238.     if ((flags & NET_TCP_FIN_FLAG) &&
  239.       ( !(tcbPtr->flags & TCP_SENT_FIN) || 
  240.       (tcbPtr->send.next == tcbPtr->send.unAck))) {
  241.     goto send;
  242.     }
  243.  
  244.     /*
  245.      * We want to send a packet if any of the following conditions hold:
  246.      *  1) we owe our peer an ACK.
  247.      *  2) we need to send a SYN or RESET flag
  248.      *  3) there's urgent data to send.
  249.      */
  250.     if ((tcbPtr->flags & TCP_ACK_NOW) ||
  251.     (flags & (NET_TCP_SYN_FLAG|NET_TCP_RST_FLAG)) ||
  252.     (TCP_SEQ_GT(tcbPtr->send.urgentPtr, tcbPtr->send.unAck))) {
  253.     goto send;
  254.     }
  255.  
  256.     /*
  257.      * Sender silly window avoidance.  If the connection is idle and we
  258.      * can send all data, either a maximum segment or at least a maximum
  259.      * default-size segment, then do it. Also send if the persist force flag 
  260.      * is set. If peer's buffer is tiny, then send when window is at least 
  261.      * half open.  If retransmitting (possibly after persist timer forced us 
  262.      * to send into a small window), then we must resend.
  263.      */
  264.     if (len != 0) {
  265.     if (len == tcbPtr->maxSegSize) {
  266.         goto send;
  267.     }
  268.     if ((idle || (tcbPtr->flags & TCP_NO_DELAY)) &&
  269.         (len + amtUnacked) >= sendBufAmtUsed) {
  270.         goto send;
  271.     }
  272.     if (tcbPtr->force ||
  273.         (len >= (tcbPtr->send.maxWindow / 2)) ||
  274.         (TCP_SEQ_LT(tcbPtr->send.next, tcbPtr->send.maxSent))) {
  275.         goto send;
  276.     }
  277.     }
  278.  
  279.     /*
  280.      * Compare the available window to amount of window known to the peer
  281.      * (i.e., advertised window less next expected input.)  If the difference
  282.      * is 35% or more of the maximum possible window, then we want to send
  283.      * a window update to the peer.
  284.      */
  285.     if (window > 0) {
  286.     int advertised = window - (tcbPtr->recv.advtWindow - tcbPtr->recv.next);
  287.     if (Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_USED) == 0 &&
  288.         advertised >= (2 * tcbPtr->maxSegSize)) {
  289.         goto send;
  290.     }
  291.     if (((100 * advertised) / 
  292.         Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE)) >= 35){
  293.         goto send;
  294.     }
  295.     }
  296.  
  297.     /*
  298.      * TCP window updates are not reliable, so a polling protocol
  299.      * using "persist" packets is used to insure receipt of window
  300.      * updates.  The three "states" for the output side are:
  301.      *      idle            not doing retransmits or persists,
  302.      *      persisting        to move a small or zero window,
  303.      *      (re)transmitting    and thereby not persisting.
  304.      *
  305.      * tcbPtr->timer[TCP_TIMER_PERSIST] is set when we are in persist state.
  306.      * tcbPtr->force  is set when we are called to send a persist packet.
  307.      * tcbPtr->timer[TCP_TIMER_REXMT]  is set when we are retransmitting
  308.      * The output side is idle when both timers are zero.
  309.      *
  310.      * If the send window is too small, and there are data to transmit, and no
  311.      * retransmit or persist timer is pending, then go to the persist state.
  312.      * If nothing happens soon, send when the timer expires:  if the window is
  313.      * nonzero, transmit what we can, otherwise force out a byte.
  314.      */
  315.  
  316.     if (sendBufAmtUsed != 0 &&
  317.     (tcbPtr->timer[TCP_TIMER_REXMT] == 0) &&
  318.     (tcbPtr->timer[TCP_TIMER_PERSIST] == 0)) {
  319.  
  320.     tcbPtr->rxtshift = 0;
  321.     TCPSetPersist(tcbPtr);
  322.     }
  323.  
  324.     /*
  325.      * No reason to send a segment, just return.
  326.      */
  327.     return(SUCCESS);
  328.  
  329. send:
  330.  
  331.     /*
  332.      * Initialize a packet and copy the data to be transmitted into the
  333.      * packet. Also, initialize the header from the template for sends 
  334.      * on this connection.
  335.      */
  336.  
  337.     IPS_InitPacket(len, &packet);
  338.  
  339.     if (len != 0) {
  340.     if (tcbPtr->force && len == 1) {
  341.         stats.tcp.send.probe++;
  342.     } else if (TCP_SEQ_LT(tcbPtr->send.next, tcbPtr->send.maxSent)) {
  343.         stats.tcp.send.rexmitPack++;
  344.         stats.tcp.send.rexmitByte += len;
  345.     } else {
  346.         stats.tcp.send.pack++;
  347.         stats.tcp.send.byte += len;
  348.     }
  349.     Sock_BufCopy(sockPtr, SOCK_SEND_BUF, amtUnacked, len, packet.data);
  350.     if (ips_Debug) {
  351.         (void) fprintf(stderr, "TCP Output: sending '%.*s'\n",
  352.         MIN(len, 20), packet.data);
  353.     }
  354.     } else if (tcbPtr->flags & TCP_ACK_NOW) {
  355.     stats.tcp.send.acks++;
  356.     } else if (flags & (NET_TCP_SYN_FLAG|NET_TCP_FIN_FLAG|NET_TCP_RST_FLAG)) {
  357.     stats.tcp.send.ctrl++;
  358.     } else if (TCP_SEQ_GT(tcbPtr->send.urgentPtr, tcbPtr->send.unAck)) {
  359.     stats.tcp.send.urg++;
  360.     } else {
  361.     stats.tcp.send.winUpdate++;
  362.     }
  363.  
  364.  
  365.     /*
  366.      * Before the ESTABLISHED state, we must send the initial options
  367.      * unless an option is set to not do any options.
  368.      */
  369.     opt = (unsigned char *) NULL;
  370.     if (TCP_UNSYNCHRONIZED(tcbPtr->state) &&
  371.     !(tcbPtr->flags & TCP_IGNORE_OPTS)) {
  372.     unsigned short mss;
  373.  
  374.     mss = MIN(Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE) / 2,
  375.              TCPCalcMaxSegSize(tcbPtr));
  376.     if (mss > NET_IP_MAX_SEG_SIZE - sizeof(Net_TCPHeader)) {
  377.         opt = (unsigned char *) &initialOptions;
  378.         optlen = sizeof(initialOptions);
  379.         initialOptions.value = Net_HostToNetShort(mss);
  380.     }
  381. #ifdef not_def
  382.     } else if (tcbPtr->tcpOptions != (Address) NULL) {
  383.     opt = (unsigned char *) tcbPtr->tcpOptions;
  384.     optlen = tcbPtr->tcpOptLen;
  385. #endif not_def
  386.     }
  387.  
  388.     /*
  389.      * Copy the options to the packet. Make sure they are padded to
  390.      * an 4-byte multiple.
  391.      */
  392.     ptr = packet.data;
  393.     if (opt != (unsigned char *) NULL) {
  394.     int padLen = 0;
  395.     while ((optlen & 0x3) != 0) {
  396.         ptr--;
  397.         *ptr = NET_TCP_OPTION_EOL;
  398.         padLen++;
  399.     }
  400.     ptr -= optlen;
  401.     bcopy((Address)opt, ptr, (int)optlen);
  402.     optlen += padLen;
  403.     }
  404.  
  405. #define tcpHdrPtr    packet.hdr.tcpPtr
  406. #define ipHdrPtr    packet.ipPtr
  407.  
  408.     tcpHdrPtr = (Net_TCPHeader *) (ptr - sizeof(Net_TCPHeader));
  409.     packet.hdrLen = sizeof(Net_TCPHeader) + optlen;
  410.     ipHdrPtr = (Net_IPHeader *)(((Address) tcpHdrPtr) - sizeof(Net_IPHeader));
  411.  
  412.     if (tcbPtr->templatePtr == (Net_TCPHeader *)NULL) {
  413.     panic("TCPOutput: no template");
  414.     }
  415.     *tcpHdrPtr = *tcbPtr->templatePtr;
  416.  
  417.  
  418.     /*
  419.      * Fill in the header fields, remembering the maximum advertised
  420.      * window for use in delaying messages about window sizes.
  421.      * If resending a FIN, be sure not to use a new sequence number.
  422.      */
  423.     if ((flags & NET_TCP_FIN_FLAG) && 
  424.     (tcbPtr->flags & TCP_SENT_FIN) && 
  425.     len == 0) {
  426.  
  427.     tcbPtr->send.next--;
  428.     }
  429.     tcpHdrPtr->seqNum = Net_HostToNetInt(tcbPtr->send.next);
  430.     tcpHdrPtr->ackNum = Net_HostToNetInt(tcbPtr->recv.next);
  431.     tcpHdrPtr->dataOffset = (sizeof(Net_TCPHeader) + optlen) >> 2;
  432.     tcpHdrPtr->flags = flags;
  433.  
  434.     /*
  435.      * Calculate the receive window size.  Don't shrink the window, but 
  436.      * avoid silly window syndrome.
  437.      */
  438.  
  439.     if (window < Sock_BufSize(sockPtr,SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE) / 4  &&
  440.     window < tcbPtr->maxSegSize) {
  441.     window = 0;
  442.     }
  443.     if (window > NET_IP_MAX_PACKET_SIZE) {
  444.     window = NET_IP_MAX_PACKET_SIZE;
  445.     }
  446.     if (window < (tcbPtr->recv.advtWindow - tcbPtr->recv.next)) {
  447.     window = tcbPtr->recv.advtWindow - tcbPtr->recv.next;
  448.     }
  449.     tcpHdrPtr->window = Net_HostToNetShort((unsigned short)window);
  450.  
  451.     if (TCP_SEQ_GT(tcbPtr->send.urgentPtr, tcbPtr->send.next)) {
  452.     tcpHdrPtr->urgentOffset = 
  453.         Net_HostToNetShort((unsigned short)(tcbPtr->send.urgentPtr - 
  454.             tcbPtr->send.next));
  455.     tcpHdrPtr->flags |= NET_TCP_URG_FLAG;
  456.     } else {
  457.     /*
  458.      * If there's no urgent pointer to send, then we pull
  459.      * the urgent pointer to the left edge of the send window
  460.      * so that it doesn't drift into the send window on sequence
  461.      * number wraparound.
  462.      */
  463.     tcbPtr->send.urgentPtr = tcbPtr->send.unAck; /* drag it along */
  464.     }
  465.  
  466.     /*
  467.      * If there's anything to send and we can send it all, set the PUSH flag.
  468.      * (This will keep happy those implementations which only give data
  469.      * to the user when a buffer fills or a PUSH comes in.)
  470.      */
  471.  
  472.     if ((len != 0) && 
  473.     ((amtUnacked+len) == Sock_BufSize(sockPtr, SOCK_SEND_BUF, 
  474.                 SOCK_BUF_USED) )) {
  475.     tcpHdrPtr->flags |= NET_TCP_PSH_FLAG;
  476.     }
  477.  
  478.     IP_FormatPacket(NET_IP_PROTOCOL_TCP,  timeToLive,
  479.             tcbPtr->IPTemplatePtr->source,
  480.             tcbPtr->IPTemplatePtr->dest, &packet);
  481.     CalcChecksum(&packet, len + optlen);
  482.  
  483.     /*
  484.      * When in the transmit state, time the transmission and arrange for
  485.      * the retransmit.  In the persist state, just set send.maxSent.
  486.      */
  487.     if ((!tcbPtr->force) || (tcbPtr->timer[TCP_TIMER_PERSIST] == 0)) {
  488.     TCPSeqNum    startSeq;
  489.  
  490.     startSeq = tcbPtr->send.next;
  491.     /*
  492.      * Advance send.next over sequence space of this segment.
  493.      */
  494.     if (flags & NET_TCP_SYN_FLAG) {
  495.         tcbPtr->send.next++;
  496.     }
  497.     if (flags & NET_TCP_FIN_FLAG) {
  498.         tcbPtr->send.next++;
  499.         tcbPtr->flags |= TCP_SENT_FIN;
  500.     }
  501.  
  502.     tcbPtr->send.next += len;
  503.     if (TCP_SEQ_GT(tcbPtr->send.next, tcbPtr->send.maxSent)) {
  504.         tcbPtr->send.maxSent = tcbPtr->send.next;
  505.  
  506.         /*
  507.          * Time this transmission if it's not a retransmission and
  508.          * we are not currently timing anything.
  509.          */
  510.         if (tcbPtr->rtt == 0) {
  511.         tcbPtr->rtt = 1;
  512.         tcbPtr->rtseq = startSeq;
  513.         stats.tcp.segsTimed++;
  514.         }
  515.     }
  516.  
  517.     /*
  518.      * Set the retransmit timer if it's not currently set
  519.      * and we're not doing an ACK or a keep-alive probe.
  520.      * The initial value for the retransmit timer is smoothed
  521.      * round-trip time + 2 * round-trip time variance.
  522.      * Also initialize the shift counter, which is used for backoff
  523.      * of retransmit time.
  524.      */
  525.     if (tcbPtr->timer[TCP_TIMER_REXMT] == 0 &&
  526.         tcbPtr->send.next != tcbPtr->send.unAck) {
  527.  
  528.         tcbPtr->timer[TCP_TIMER_REXMT] = tcbPtr->rxtcur;
  529.         if (tcbPtr->timer[TCP_TIMER_PERSIST] != 0) {
  530.         tcbPtr->timer[TCP_TIMER_PERSIST] = 0;
  531.         tcbPtr->rxtshift = 0;
  532.         }
  533.     }
  534.     } else {
  535.     if (TCP_SEQ_GT(tcbPtr->send.next + len, tcbPtr->send.maxSent)) {
  536.         tcbPtr->send.maxSent = tcbPtr->send.next + len;
  537.     }
  538.     }
  539.  
  540.     /*
  541.      * Trace this operation if debugging is set.
  542.      */
  543.  
  544.     if (Sock_IsOptionSet(sockPtr, NET_OPT_DEBUG)) {
  545.     TCPTrace(TCP_TRACE_OUTPUT, tcbPtr->state, tcbPtr, tcpHdrPtr, len);
  546.     }
  547.     if (ips_Debug) {
  548.     (void) fprintf(stderr, 
  549.             "TCP Output: %d bytes <%x,%d,#%d> -> <%x,%d>\n\t", 
  550.             len, 
  551.             Net_NetToHostInt(ipHdrPtr->source), 
  552.             Net_NetToHostShort(tcpHdrPtr->srcPort), 
  553.             Net_NetToHostShort(ipHdrPtr->ident),
  554.             Net_NetToHostInt(ipHdrPtr->dest), 
  555.             Net_NetToHostShort(tcpHdrPtr->destPort));
  556.     TCPPrintHdrFlags(stderr, tcpHdrPtr->flags);
  557.     (void) fprintf(stderr, "  seq=%d, ack=%d, wind=%d\n", 
  558.         Net_NetToHostInt(tcpHdrPtr->seqNum), 
  559.         Net_NetToHostInt(tcpHdrPtr->ackNum),
  560.         Net_NetToHostShort(tcpHdrPtr->window));
  561.     }
  562.  
  563.  
  564.     IP_QueueOutput(&packet);
  565. #ifdef old_way
  566.     {
  567.     ReturnStatus    status;
  568.     status = IP_Output(&packet, TRUE);
  569.     free(packet.base);
  570.     if (status != SUCCESS) {
  571.         return(status);
  572.     }
  573.     }
  574. #endif old_way
  575.  
  576.     stats.tcp.send.total++;
  577.  
  578.     /*
  579.      * The data have been sent (as far as we can tell). If this advertises a 
  580.      * larger window than any other segment, then remember the size of 
  581.      * the advertised window. Any pending ACK has now been sent.
  582.      */
  583.  
  584.     if ((window > 0) && 
  585.     TCP_SEQ_GT(tcbPtr->recv.next + window, tcbPtr->recv.advtWindow)) {
  586.     tcbPtr->recv.advtWindow = tcbPtr->recv.next + window;
  587.     }
  588.  
  589.     tcbPtr->flags &= ~(TCP_ACK_NOW | TCP_DELAY_ACK);
  590.  
  591.     if (sendAlot) {
  592.     goto again;
  593.     }
  594.     return(SUCCESS);
  595. #undef tcpHdrPtr
  596. #undef ipHdrPtr
  597. }
  598.  
  599.  
  600. /*
  601.  *----------------------------------------------------------------------
  602.  *
  603.  * TCPRespond --
  604.  *
  605.  *    Send a single message to the TCP at address specified by
  606.  *    the given TCP/IP header.  If flags==0, then we make a copy
  607.  *    of the tcpiphdr at ti and send directly to the addressed host.
  608.  *    This is used to force keep alive messages out using the TCP
  609.  *    template for a connection *tcbPtr->templatePtr.  If flags are given
  610.  *    then we send a message back to the TCP which originated the
  611.  *    segment ti, and discard the mbuf containing it and any other
  612.  *    attached mbufs.
  613.  *
  614.  *    In any case the ack and sequence number of the transmitted
  615.  *    segment are as specified by the parameters.
  616.  *
  617.  * Results:
  618.  *    None.
  619.  *
  620.  * Side effects:
  621.  *    A packet is sent to the remote peer.
  622.  *
  623.  *----------------------------------------------------------------------
  624.  */
  625.  
  626. void
  627. TCPRespond(sockPtr, tcpHdrPtr, ipHdrPtr, ack, seq, flags)
  628.     Sock_InfoPtr    sockPtr;    /* Socket that is sending a response. */
  629.     register Net_TCPHeader *tcpHdrPtr;    /* TCP header from the packet we are
  630.                      * responding to. */
  631.     register Net_IPHeader *ipHdrPtr;    /* IP header from the the packet. */
  632.     TCPSeqNum        ack;        /* Ack and sequence numbers, flags 
  633.                      * to be sent. */
  634.     TCPSeqNum        seq;
  635.     int         flags;
  636. {
  637.     int         window = 0;
  638.     IPS_Packet        packet;
  639.  
  640.     if (sockPtr != (Sock_InfoPtr) NULL) {
  641.     window = Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_FREE);
  642.     }
  643.  
  644.     IPS_InitPacket(tcpKeepLen, &packet);
  645.  
  646.     if (flags == 0) {
  647.     /*
  648.      * We're sending a response because of a time-out.
  649.      */
  650.     packet.dataLen = tcpKeepLen;
  651.     flags = NET_TCP_ACK_FLAG;
  652.     } else {
  653.     /*
  654.      * We're sending a response back to the origin. Swap the source
  655.      * and destination addresses and ports from the packet.
  656.      */
  657.     packet.dataLen = 0;
  658. #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
  659.     xchg(ipHdrPtr->dest, ipHdrPtr->source, Net_InetAddress);
  660.     xchg(tcpHdrPtr->destPort, tcpHdrPtr->srcPort, unsigned short);
  661. #undef xchg
  662.     }
  663.     packet.hdr.tcpPtr = (Net_TCPHeader *) (packet.data - sizeof(Net_TCPHeader));
  664.     packet.hdrLen = sizeof(Net_TCPHeader);
  665.     packet.ipPtr = (Net_IPHeader *) ((Address)packet.hdr.tcpPtr - 
  666.             sizeof(Net_IPHeader));
  667.  
  668.     *packet.hdr.tcpPtr = *tcpHdrPtr;
  669.     packet.hdr.tcpPtr->seqNum        = Net_HostToNetInt(seq);
  670.     packet.hdr.tcpPtr->ackNum        = Net_HostToNetInt(ack);
  671.     packet.hdr.tcpPtr->dataOffset    = sizeof(Net_TCPHeader) >> 2;
  672.     packet.hdr.tcpPtr->urgentOffset    = 0;
  673.     packet.hdr.tcpPtr->flags        = flags;
  674.     packet.hdr.tcpPtr->window       = Net_HostToNetShort((unsigned short)window);
  675.  
  676.  
  677.     IP_FormatPacket(NET_IP_PROTOCOL_TCP,  timeToLive,
  678.             ipHdrPtr->source, ipHdrPtr->dest, &packet);
  679.  
  680.     if (ips_Debug) {
  681.     (void) fprintf(stderr, 
  682.             "TCP Respond:  <%x,%d,#%d> -> <%x,%d>\n\t", 
  683.             Net_NetToHostInt(ipHdrPtr->source), 
  684.             Net_NetToHostShort(packet.hdr.tcpPtr->srcPort), 
  685.             Net_NetToHostShort(ipHdrPtr->ident),
  686.             Net_NetToHostInt(ipHdrPtr->dest), 
  687.             Net_NetToHostShort(packet.hdr.tcpPtr->destPort));
  688.     TCPPrintHdrFlags(stderr, (unsigned short)flags);
  689.     (void) fprintf(stderr, "  seq=%d, ack=%d, wind=%d\n", 
  690.         Net_NetToHostInt(packet.hdr.tcpPtr->seqNum), 
  691.         Net_NetToHostInt(packet.hdr.tcpPtr->ackNum),
  692.         Net_NetToHostShort(packet.hdr.tcpPtr->window));
  693.     }
  694.     CalcChecksum(&packet, packet.dataLen);
  695.  
  696.  
  697.     (void) IP_Output(&packet, TRUE);
  698.     free(packet.base);
  699. }
  700.  
  701.  
  702. /*
  703.  *----------------------------------------------------------------------
  704.  *
  705.  * CalcChecksum --
  706.  *
  707.  *    Calculates the checksum for the TCP header, pseudo-header and data.
  708.  *    It is assumed that the data immediately follows the TCP header.
  709.  *    The data may include TCP header options.
  710.  *
  711.  * Results:
  712.  *    None.
  713.  *
  714.  * Side effects:
  715.  *    None.
  716.  *
  717.  *----------------------------------------------------------------------
  718.  */
  719.  
  720. static void
  721. CalcChecksum(packetPtr, len)
  722.     IPS_Packet *packetPtr;    /* Packet descriptor. */
  723.     int        len;        /* Length of data following the TCP header. */ 
  724. {
  725.     Net_IPPseudoHdr    pseudoHdr;
  726.     Net_TCPHeader    *tcpPtr = packetPtr->hdr.tcpPtr;
  727.     Net_IPHeader    *ipPtr  = packetPtr->ipPtr;
  728.  
  729.     len += sizeof(Net_TCPHeader);
  730.     pseudoHdr.source    = (ipPtr->source);
  731.     pseudoHdr.dest    = (ipPtr->dest);
  732.     pseudoHdr.zero    = 0;
  733.     pseudoHdr.protocol    = NET_IP_PROTOCOL_TCP;
  734.     pseudoHdr.len    = Net_HostToNetShort(len);
  735.     tcpPtr->checksum = 0;
  736.     tcpPtr->checksum = Net_InetChecksum2(len, (Address) tcpPtr, &pseudoHdr);
  737. }
  738. @
  739.  
  740.  
  741. 1.7
  742. log
  743. @Fixed up debugging info.
  744. @
  745. text
  746. @d25 1
  747. a25 1
  748. static char rcsid[] = "$Header: tcpOutput.c,v 1.2 89/06/08 20:18:35 mnelson Exp $ SPRITE (Berkeley)";
  749. d498 1
  750. a498 1
  751.     (void) fprintf(stderr, "  seq=%d, ack=%d\n", 
  752. d500 2
  753. a501 1
  754.         Net_NetToHostInt(tcpHdrPtr->ackNum));
  755. d622 7
  756. a628 6
  757.     (void) fprintf(stderr, "TCP Respond: <%x,%d,#%d> --> <%x, %d>  ", 
  758.             Net_NetToHostInt(ipHdrPtr->source), 
  759.             Net_NetToHostShort(packet.hdr.tcpPtr->srcPort), 
  760.             packet.ipPtr->ident,
  761.             Net_NetToHostInt(ipHdrPtr->dest), 
  762.             Net_NetToHostShort(packet.hdr.tcpPtr->destPort));
  763. d630 4
  764. a633 1
  765.     (void) fprintf(stderr, "\n");
  766. @
  767.  
  768.  
  769. 1.6
  770. log
  771. @Removed stdio.h include
  772. @
  773. text
  774. @d25 1
  775. a25 1
  776. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpOutput.c,v 1.5 89/02/21 10:14:05 brent Exp $ SPRITE (Berkeley)";
  777. d492 5
  778. a496 4
  779.             ipHdrPtr->source, 
  780.             (tcpHdrPtr->srcPort), ipHdrPtr->ident,
  781.             ipHdrPtr->dest, 
  782.             (tcpHdrPtr->destPort));
  783. d499 2
  784. a500 1
  785.         tcpHdrPtr->seqNum, tcpHdrPtr->ackNum);
  786. d622 2
  787. a623 2
  788.             ipHdrPtr->source, 
  789.             (packet.hdr.tcpPtr->srcPort), 
  790. d625 2
  791. a626 2
  792.             ipHdrPtr->dest, 
  793.             (packet.hdr.tcpPtr->destPort));
  794. @
  795.  
  796.  
  797. 1.5
  798. log
  799. @Updated interface to IP_Output
  800. @
  801. text
  802. @d25 1
  803. a25 1
  804. static char rcsid[] = "$Header: tcpOutput.c,v 1.4 88/09/15 09:33:55 mendel Exp $ SPRITE (Berkeley)";
  805. a35 2
  806.  
  807. #include <stdio.h>
  808. @
  809.  
  810.  
  811. 1.4
  812. log
  813. @Added/removed byte swapping for SPUR.
  814. @
  815. text
  816. @d25 1
  817. a25 1
  818. static char rcsid[] = "$Header: tcpOutput.c,v 1.3 88/08/16 11:20:22 mendel Exp $ SPRITE (Berkeley)";
  819. d508 1
  820. a508 1
  821.     status = IP_Output(&packet);
  822. d633 1
  823. a633 1
  824.     (void) IP_Output(&packet);
  825. @
  826.  
  827.  
  828. 1.3
  829. log
  830. @Converted to use new libc.a
  831. @
  832. text
  833. @d25 1
  834. a25 1
  835. static char rcsid[] = "$Header: tcpOutput.c,v 1.2 88/04/27 09:10:23 brent Exp $ SPRITE (Berkeley)";
  836. d494 4
  837. a497 2
  838.             ipHdrPtr->source, tcpHdrPtr->srcPort, ipHdrPtr->ident,
  839.             ipHdrPtr->dest, tcpHdrPtr->destPort);
  840. a618 1
  841.     CalcChecksum(&packet, packet.dataLen);
  842. d622 2
  843. a623 1
  844.             ipHdrPtr->source, packet.hdr.tcpPtr->srcPort, 
  845. d625 2
  846. a626 1
  847.             ipHdrPtr->dest, packet.hdr.tcpPtr->destPort);
  848. d630 1
  849. d632 1
  850. d666 2
  851. a667 2
  852.     pseudoHdr.source    = ipPtr->source;
  853.     pseudoHdr.dest    = ipPtr->dest;
  854. @
  855.  
  856.  
  857. 1.2
  858. log
  859. @New update with Jacobson enhancements
  860. @
  861. text
  862. @d25 1
  863. a25 1
  864. static char rcsid[] = "$Header: tcpOutput.c,v 6.1 88/04/24 23:14:55 andrew Exp $ SPRITE (Berkeley)";
  865. d37 1
  866. a37 4
  867. #include "byte.h"
  868. #include "io.h"
  869. #include "sys.h"
  870. #include "mem.h"
  871. d294 1
  872. a294 1
  873.         Io_PrintStream(io_StdErr, "TCP Output: sending '%.*s'\n",
  874. d344 1
  875. a344 1
  876.     Byte_Copy((int)optlen, (Address)opt, ptr);
  877. d356 1
  878. a356 1
  879.     Sys_Panic(SYS_FATAL, "TCPOutput: no template");
  880. d491 1
  881. a491 1
  882.     Io_PrintStream(io_StdErr, 
  883. d496 2
  884. a497 2
  885.     TCPPrintHdrFlags(io_StdErr, tcpHdrPtr->flags);
  886.     Io_PrintStream(io_StdErr, "  seq=%d, ack=%d\n", 
  887. d507 1
  888. a507 1
  889.     Mem_Free(packet.base);
  890. d620 1
  891. a620 1
  892.     Io_PrintStream(io_StdErr, "TCP Respond: <%x,%d,#%d> --> <%x, %d>  ", 
  893. d624 2
  894. a625 2
  895.     TCPPrintHdrFlags(io_StdErr, (unsigned short)flags);
  896.     Io_PrintStream(io_StdErr, "\n");
  897. d629 1
  898. a629 1
  899.     Mem_Free(packet.base);
  900. @
  901.  
  902.  
  903. 1.1
  904. log
  905. @Initial revision
  906. @
  907. text
  908. @d6 1
  909. a6 1
  910.  *    Based on 4.3BSD    @@(#)tcp_output.c    7.5 (Berkeley) 6/6/87
  911. d25 1
  912. a25 1
  913. static char rcsid[] = "$Header: tcpOutput.c,v 6.0 87/09/08 15:57:07 andrew Stable $ SPRITE (Berkeley)";
  914. d140 1
  915. a140 1
  916.         tcbPtr->retransShift = 0;
  917. d160 2
  918. a161 7
  919.     if (flags & NET_TCP_FIN_FLAG) {
  920.         if (tcbPtr->flags & TCP_ACK_NOW) {
  921.         len = 0;
  922.         } else {
  923.         return(SUCCESS);
  924.         }
  925.     } else if (window == 0) {
  926. a163 3
  927.         len = 0;
  928.     } else {
  929.         return(SUCCESS);
  930. d211 1
  931. a211 1
  932.     if (len == tcbPtr->maxSegSize || len >= NET_TCP_MAX_SEG_SIZE) {
  933. d231 10
  934. a240 4
  935.     if ((window > 0) && 
  936.     ((100 * (window - (tcbPtr->recv.advtWindow - tcbPtr->recv.next)) / 
  937.         Sock_BufSize(sockPtr,SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE)) >= 35)){
  938.     goto send;
  939. d266 1
  940. a266 1
  941.     tcbPtr->retransShift = 0;
  942. d389 2
  943. a390 2
  944.     if (window < (int)(tcbPtr->recv.advtWindow - tcbPtr->recv.next)) {
  945.     window = (int)(tcbPtr->recv.advtWindow - tcbPtr->recv.next);
  946. d392 3
  947. d434 3
  948. d456 3
  949. a458 3
  950.         if (tcbPtr->roundTripTime == 0) {
  951.         tcbPtr->roundTripTime = 1;
  952.         tcbPtr->rttSeqNum = tcbPtr->send.next - len;
  953. d466 2
  954. a467 2
  955.      * The initial value for the retransmit timer is 
  956.      *     tcp_SmoothBeta*tcbPtr->smoothRTT.
  957. d474 5
  958. a478 6
  959.         TCP_TIMER_RANGESET(tcbPtr->timer[TCP_TIMER_REXMT],
  960.           tcpSmoothBeta * 
  961.           (tcbPtr->smoothRTT ? tcbPtr->smoothRTT : TCP_SRTT_DEFLT_TIME),
  962.           TCP_MIN_REXMT_TIME, TCP_MAX_REXMT_TIME);
  963.         tcbPtr->retransShift = 0;
  964.         tcbPtr->timer[TCP_TIMER_PERSIST] = 0;
  965. d526 1
  966. a526 1
  967.     TCP_SEQ_GT(tcbPtr->recv.next+window, tcbPtr->recv.advtWindow)) {
  968. @
  969.